
#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include "TcpServer.hpp"
#include "Protocal.hpp"
#include "Calculate.hpp"
using namespace protocol_ns;
using std::cout;
using std::endl;

void Usage(const char *arg)
{
    cout << "USAGE:" << endl;
    cout << "#         please enter: " << arg << "serverport" << endl;
}
using service_what = std::function<Response(const Request &req)>;
class TheService
{
public:
    TheService(service_what cb)
        : _cb(cb) {}
    ~TheService() {}

    void service(socket_sptr sptr, InetAddr addr)
    {
        int fd = sptr->returnfd();
        LOG(INFO, "server get a new link,ip is %s,port is %d", addr.Ip().c_str(), addr.Port());
        std::string inbuffer;
        sleep(6);

        while (true)
        {
            int n = sptr->Recv(&inbuffer);
            if (n == 0)
            {
                LOG(INFO, "client quit,ip is %s,port is %d", addr.Ip().c_str(), addr.Port());
                return;
            }
            std::string message = Decode(inbuffer);
            while (!message.empty())
            {
                LOG(DEBUG, "get whole json %s", message.c_str());
                Request req;
                req.DeSerialize(message);
                Response response = _cb(req);
                std::string ret;
                response.Serialize(&ret);
                // LOG(DEBUG, "Serialize ret %s", ret.c_str());
                ret = Encode(ret);
                LOG(DEBUG, "Encode ret %s", ret.c_str());
                sptr->Send(ret);
                message = Decode(inbuffer);
            }
        }
    }

private:
    service_what _cb;
};
// ./server 8888
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }
    Enablescreen();
    uint16_t port = std::stoi(argv[1]);
    Calculate cal;
    TheService theservice(std::bind(&Calculate::Excute, &cal, std::placeholders::_1));
    std::unique_ptr<TcpServer> uptr = std::make_unique<TcpServer>(port, std::bind(&TheService::service, &theservice, std::placeholders::_1, std::placeholders::_2));
    uptr->StartServer();
    return 0;
}

// int main()
// {
//     Enablescreen();
//     // TcpSocket server;
//     UdpSocket server;
//     InetAddr serveraddr("0", 8888);
//     // server.BuildListenSocket(serveraddr);
//     server.BuildUdpServerSocket(serveraddr);
//     // InetAddr addr; // client
//     int fd=server.returnfd();
//     // int fd = server.AcceptIt(&addr)->returnfd();

//     while (true)
//     {
//     InetAddr addr; // client
//     struct sockaddr_in tmp=addr.Addr();
//     socklen_t len=sizeof(tmp);
//         char buffer[1024];
//         int n = recvfrom(fd, buffer, sizeof(buffer) - 1, 0,(struct sockaddr*)&tmp,&len);
//         if (n > 0)
//         {
//             buffer[n] = 0;
//             LOG(INFO, "[%s:%d]#%s", addr.Ip().c_str(), addr.Port(), buffer);
//             std::string message = "server echo#";
//             message += buffer;
//             sendto(fd, message.c_str(), message.size(), 0,(struct sockaddr*)&tmp,len);
//         }
//         else if (n < 0) // 读取出错
//         {
//             LOG(ERROR, "read error");
//             break;
//         }
//         else // n==0 client退出&&关闭连接
//         {
//             LOG(INFO, "[%s,%d] quit", addr.Ip().c_str(), addr.Port());
//             break;
//         }
//     }

//     return 0;
// }